﻿
namespace FreeNode.ForEgret3D {
    export class FileGroup {
        matrefs: string[] = [];//材质比较特殊
        prefabCount: number = 0;
        prefabs: { [id: string]: Entity_Empty | Entity_Mesh } = {};
        texCount: number = 0;
        texs: { [id: string]: egret3d.ITexture } = {};
        geomCount: number = 0;
        geoms: { [id: string]: egret3d.Geometry } = {};
        aniCount: number = 0;
        anis: { [id: string]: AniClipData } = {};
    }
    export interface IParser2 {
        ParseNode(parser: SceneParser2, json: {}, parent: any): any;//处理节点

        ParseComponent(parser: SceneParser2, json: {}, parent: any): any;//处理组件

        DelayParse(): void;
    }
    export class SceneParser2 {
        parser: IParser2;
        constructor(parser: IParser2) {
            this.parser = parser;
        }

        public ParseScene(json: any): any {
            var obj = this._parseNode(json, null);
            this.parser.DelayParse();
            return obj;
        }
        private _parseNode(json: {}, pnode: any): any {
            var name = <string>json["name"];
            var node = this.parser.ParseNode(this, json, pnode);
            //console.log("pnode:" + name);
            if (node != null) {
                var components = json["components"];
                if (components != undefined)
                    for (var i = 0; i < components.length; i++) {
                        var type = components[i]["type"];
                        //console.log("pcom:" + type);
                        this.parser.ParseComponent(this, components[i], node);
                    }
                var children = json["children"];
                if (children != undefined)
                    for (var i = 0; i < children.length; i++) {
                        this._parseNode(children[i], node);
                    }
            }
            return node;
        }

        static readString(data: DataView, seek: number): number {
            var slen = data.getUint8(seek);
            seek++;
            var bs: number[] = [];
            for (var i = 0; i < slen; i++) {
                bs.push(data.getUint8(seek));
                seek++;
            }
            return seek;
        }



    }
    export class Parser2 implements IParser2 {
        constructor() {
            this.delaycall = [];
            this.mapNode = {};
        }
        delaycall: Array<Function>;
        mapNode: { [id: number]: (Entity_Empty | Entity_Mesh) };
        ParseNode(parser: SceneParser2, json: {}, parent: any): any//处理节点
        {
            if (json["empty"] == 1) {
                return null;
            }
            //判断是否是mesh组件
            var components = json["components"];
            var ismesh = false;
            var issmesh = false;
            var needupdate = false;
            var hasBoxCollider = false;
            if (components != undefined) {
                for (var i in components) {
                    if (components[i]["type"] == "meshfilter") {
                        ismesh = true;
                    }
                    if (components[i]["type"] == "skinnedmeshrenderer") {
                        issmesh = true;
                    }
                    if (components[i]["type"] == "aniplayer") {
                        needupdate = true;
                    }
                    if (components[i]["type"] == "boxcollider") {
                        hasBoxCollider = true;
                    }
                }
            }

            var n: any = null;
            if (ismesh == true) {
                n = new Entity_Mesh();
            }
            else if (issmesh == true) {
                n = new Entity_Mesh();
            }
            else if (needupdate == true) {
                n = new Entity_Mesh();
            } else if (hasBoxCollider) {
                n = new Entity_Mesh();
            }
            else {
                n = new Entity_Empty();
                //n.geometry = new egret3d.CubeGeometry(0.05, 0.05, 0.05);
            }
            n.name = json["name"];
            n.uuid = json["id"];
            if (parent != null) {
                var pobj = <egret3d.Object3D>parent;
                pobj.addChild(n);
                if (n.parent instanceof (Entity_Empty) || n.parent instanceof (Entity_Mesh)) {
                    n.fullname = n.parent.fullname + "/" + n.name;
                }
                else {
                    n.fullname = n.name;
                }
            }
            else {
                n.fullname = n.name;
                //this.view.addChild3D(n);
            }
            this.mapNode[n.uuid] = n;
            //console.log("parseNode:" + n.fullname + "|" + n.uuid + " ismesh:" + ismesh);

            return n;
        }
        ParseComponent(parser: SceneParser2, json: {}, parent: any): any//处理组件
        {
            if (json["type"] == "transform") {
                this._parseTransform(json, parent);
            }
            else if (json["type"] == "meshfilter") {
                this._parseMeshFilter(json, parent);
            }
            else if (json["type"] == "asbone") {
                var playerobj = Skinner._findPlayerObj(parent);
                if (playerobj != null && playerobj.aniplayer != null) {
                    playerobj.aniplayer.care(parent);
                }
            }
            else if (json["type"] == "meshrenderer") {
                this._parseMeshRenderer(json, parent);
            }
            else if (json["type"] == "skinnedmeshrenderer") {
                this._parseSkinnedMeshRenderer(json, parent);
            }
            else if (json["type"] == "aniplayer") {
                this._parseAniPlayer(json, parent);
            } else if (json["type"] == "boxcollider") {
                this._parseBoxCollider(json, parent);
            }
            else {
                console.warn("not parse com:" + json["type"]);
                return;
            }
            //console.log("parse com:" + json["type"]);
        }
        DelayParse(): void {
            for (var i = 0; i < this.delaycall.length; i++) {
                this.delaycall[i]();
            }
            this.delaycall = null;
        }
        _parseTransform(json: {}, node: Entity_Empty) {

            var sp = (<string>json["transmove"]).split(",");
            var vec3: egret3d.Vector3D = new egret3d.Vector3D(parseFloat(sp[0]), parseFloat(sp[1]), parseFloat(sp[2]));
            node.position = vec3;

            var sp1 = (<string>json["transscale"]).split(",");
            var scale3: egret3d.Vector3D = new egret3d.Vector3D(parseFloat(sp1[0]), parseFloat(sp1[1]), parseFloat(sp1[2]));
            node.scale = scale3;


            var sp2 = (<string>json["transquat"]).split(",");
            var x = parseFloat(sp2[0]);
            var y = parseFloat(sp2[1]);
            var z = parseFloat(sp2[2]);// * -1;
            var w = parseFloat(sp2[3]);// * -1;
            var quat = new egret3d.Quaternion(x, y, z, w);
            var ruler3 = quat.toEulerAngles();
            node.orientation = quat;

            //console.log("name=" + node.name + "vec3=" + vec3.toString() + " scale3=" + scale3.toString() + " ruler3=" + ruler3.toString());

        }
        _parseMeshFilter(json: {}, node: Entity_Mesh) {
            var meshname = <string>json["mesh"];
            var geom = ResourceMgr.instance().mapMesh[meshname].data;
            node.geometry = geom;
            node.rebuildBoundBox();
            //geom.buildGeomtry();
            //geom.buildBoundBox();
        }
        _parseMeshRenderer(json: {}, node: Entity_Mesh) {
            var playerobj = Skinner._findPlayerObj(node);
            if (playerobj != null && playerobj.aniplayer != null) {
                playerobj.aniplayer.care(node);
            }
            for (var i = 0; i < json["mats"].length; i++) {
                var matstr: string = json["mats"][0];

                let mat = new egret3d.TextureMaterial();
                ResourceMgr.instance().parseMat(matstr, mat);
                if (mat != undefined) {

                    node.addSubMaterial(i, mat);
                    if (i == 0)
                        node.material = mat;
                }
            }
        }
        numskinner: number = 0;
        _parseSkinnedMeshRenderer(json: {}, node: Entity_Mesh) {
            var geom = <egret3d.Geometry>node.geometry;
            var meshname = <string>json["mesh"];
            //var mesh = parent;
            if (meshname == "")
                return;

            this.numskinner++;
            //if (this.numskinner <= 3)
            {
                var geom = ResourceMgr.instance().mapMesh[meshname].data;
                node.geometry = geom;
                node.rebuildBoundBox();
                var playerobj = Skinner._findPlayerObj(node);
                var skinner = new Skinner(json["boneobjs"], playerobj);

                var gc = geom["maxbone"] + 1;
                var bc = skinner.bones.length;
                //var tpose = geom["tpose"];

                if (gc > bc) throw new Error("error bone count");

                if (playerobj != null) {
                    //(playerobj as Entity_Mesh).aniplayer.uploadTpose(tpose, skinner.bones);
                }
                node.animation = skinner;
                for (var i = 0; i < json["mats"].length; i++) {
                    var matstr: string = json["mats"][i];

                    let mat = new egret3d.TextureMaterial();
                    ResourceMgr.instance().parseMat(matstr, mat);
                    if (mat != undefined) {

                        node.addSubMaterial(i, mat);
                        if (i == 0)
                            node.material = mat;
                    }
                }
            }
        }
        _parseAniPlayer(json: {}, node: Entity_Mesh): void {
            var aplayer = new AniPlayer(node);
            node.aniplayer = aplayer;
            var anis: { [id: string]: FreeNode.AniClipData } = {};
            for (var i = 0; i < (json["clips"]).length; i++) {
                var clipfilename = json["clips"][i];
                console.log(clipfilename);
                var clip = ResourceMgr.instance().mapAniClip[clipfilename].data;
                aplayer.clips[clip.name] = clip;
            }


            for (var i = 0; i < (json["bones"]).length; i++) {
                var bitem = json["bones"][i];
                var name = bitem["name"];
                var qs = (bitem["tposeq"] as string).split(",");
                var ts = (bitem["tposet"] as string).split(",");

                var nb = new FreeNode.PoseBoneMatrix();
                nb.r = new FreeNode.Quaternion(parseFloat(qs[0]), parseFloat(qs[1]), parseFloat(qs[2]), parseFloat(qs[3]));
                nb.t = new FreeNode.Vector3(parseFloat(ts[0]), parseFloat(ts[1]), parseFloat(ts[2]));
                nb.invert();
                //var q = new egret3d.Quaternion(parseFloat(qs[0]), parseFloat(qs[1]), parseFloat(qs[2]), parseFloat(qs[3]));
                //var t = new egret3d.Vector3D(parseFloat(ts[0]), parseFloat(ts[1]), parseFloat(ts[2]));

                //var tmat = new egret3d.Matrix4_4();
                //tmat.makeTransform(t, new egret3d.Vector3D(1, 1, 1), q);
                //tmat.invert();
                //var arr: any = [q, t];
                aplayer.tpose[name] = nb;
                aplayer.nowpose[name] = FreeNode.PoseBoneMatrix.createDefault();
            }


            this.delaycall.push(() => {
                //delay fillbone name
                //自动播放第零个骨骼动画
                if (aplayer.getAnimList().length > 0) {
                    aplayer.play(aplayer.getAnimList()[0]);
                }
            }
            );
            //node.comps.push(anis);

        }

        _parseBoxCollider(json: {}, node: Entity_Mesh): void {
            var center: string = json["center"];
            var size: string = json["size"];
            var centerArray: Array<string> = center.split(",");
            var sizeArray: Array<string> = size.split(",");
            var min = new egret3d.Vector3D(+centerArray[0] - (+sizeArray[0]) * 0.5, +centerArray[1] - (+sizeArray[1]) * 0.5, +centerArray[2] - (+sizeArray[2]) * 0.5);
            var max = new egret3d.Vector3D(+centerArray[0] + (+sizeArray[0]) * 0.5, +centerArray[1] + (+sizeArray[1]) * 0.5, +centerArray[2] + (+sizeArray[2]) * 0.5);
            var bound: egret3d.BoundBox = new egret3d.BoundBox(node, min, max);
            node.bound = bound;
            //node.bound.visible = true;
        }
    }

    export class ResourceMgr {
        static g_this: ResourceMgr = null;
        static instance() {
            if (ResourceMgr.g_this == null)
                ResourceMgr.g_this = new ResourceMgr();
            return ResourceMgr.g_this;
        }
        private lightgroup: egret3d.LightGroup;
        init(lightgroup: egret3d.LightGroup) {
            this.lightgroup = lightgroup;
        }
        private __FillGeomVertex(verticesData: number[], _data: MeshData, withskin: boolean): number {
            var maxbone: number = 0;
            for (var i = 0; i < _data.vec3positions.length / 3; i++) {
                //egret3d.VertexFormat.VF_POSITION
                var x = _data.vec3positions[i * 3 + 0];
                var y = _data.vec3positions[i * 3 + 1];
                var z = _data.vec3positions[i * 3 + 2];

                //egret3d 计算系统有坑，先乘以2
                verticesData.push(x);
                verticesData.push(y);
                verticesData.push(z);
                //| egret3d.VertexFormat.VF_NORMAL
                if (_data.vec3normals != null) {
                    var nx = _data.vec3normals[i * 3 + 0];
                    var ny = _data.vec3normals[i * 3 + 1];
                    var nz = _data.vec3normals[i * 3 + 2];
                    verticesData.push(nx);//normal
                    verticesData.push(ny);
                    verticesData.push(nz);
                }
                else {
                    verticesData.push(0);//normal
                    verticesData.push(0);
                    verticesData.push(0);
                }
                // | egret3d.VertexFormat.VF_TANGENT 
                if (_data.vec4tangents != null) {
                    var nx = _data.vec4tangents[i * 4 + 0];
                    var ny = _data.vec4tangents[i * 4 + 1];
                    var nz = _data.vec4tangents[i * 4 + 2];
                    verticesData.push(nx);//tangent
                    verticesData.push(ny);
                    verticesData.push(nz);
                }
                else {
                    verticesData.push(0);//tangent
                    verticesData.push(0);
                    verticesData.push(0);
                }
                //| egret3d.VertexFormat.VF_COLOR
                if (_data.vec4colors != null) {
                    var r = _data.vec4colors[i * 4 + 0];
                    var g = _data.vec4colors[i * 4 + 1];
                    var b = _data.vec4colors[i * 4 + 2];
                    var a = _data.vec4colors[i * 4 + 3];
                    r = 1;
                    g = 1;
                    b = 1;
                    a = 1;
                    verticesData.push(r);//color
                    verticesData.push(g);
                    verticesData.push(b);
                    verticesData.push(a);
                }
                else {
                    verticesData.push(1);//color
                    verticesData.push(1);
                    verticesData.push(1);
                    verticesData.push(1);
                }
                //| egret3d.VertexFormat.VF_UV0 
                if (_data.vec2uvs0 != null) {
                    var uvx = _data.vec2uvs0[i * 2 + 0];
                    var uvy = _data.vec2uvs0[i * 2 + 1];
                    verticesData.push(uvx);//uv0
                    verticesData.push(1 - uvy);
                }
                else {
                    verticesData.push(0);//uv0
                    verticesData.push(0);
                }
                //| egret3d.VertexFormat.VF_UV1;

                if (_data.vec2uvs1 != null) {
                    var uvx = _data.vec2uvs1[i * 2 + 0];
                    var uvy = _data.vec2uvs1[i * 2 + 1];
                    verticesData.push(uvx);//uv1
                    verticesData.push(1 - uvy);
                }
                else {
                    verticesData.push(0);//uv1
                    verticesData.push(0);
                }
                if (withskin == true) {
                    if (_data.vec8widget != null) {
                        //var i0 = _data.vec8widget[i * 8 + 0];
                        //var w0 = _data.vec8widget[i * 8 + 4];
                        //console.warn("bw=" + i0 + "=" + w0);
                        for (var k = 0; k < 4; k++) {
                            maxbone = Math.max(_data.vec8widget[i * 8 + k], maxbone);
                        }
                        verticesData.push(_data.vec8widget[i * 8 + 0]);//index0;
                        verticesData.push(_data.vec8widget[i * 8 + 1]);//index1
                        verticesData.push(_data.vec8widget[i * 8 + 2]);//index2
                        verticesData.push(_data.vec8widget[i * 8 + 3]);//index3
                        verticesData.push(_data.vec8widget[i * 8 + 4]);//widget0;
                        verticesData.push(_data.vec8widget[i * 8 + 5]);//widget1
                        verticesData.push(_data.vec8widget[i * 8 + 6]);//widget2
                        verticesData.push(_data.vec8widget[i * 8 + 7]);//widget3

                    }
                    else {
                        verticesData.push(0);//index0;
                        verticesData.push(0);//index1
                        verticesData.push(0);//index2
                        verticesData.push(0);//index3
                        verticesData.push(0);//widget0;
                        verticesData.push(0);//widget1
                        verticesData.push(0);//widget2
                        verticesData.push(0);//widget3

                    }
                }
            }
            return maxbone;
        }
        private __FillGeomIndex(geom: egret3d.Geometry, _data: MeshData): void {
            let indexData = [];
            //geom.indexData = [];
            geom.subGeometrys = [];
            //geom.numItems = geom.indexData.length;
            for (var k = 0; k < _data.indices.length; k++)//_data.indices.length; i++)
            {
                var sg: egret3d.SubGeometry = new egret3d.SubGeometry();
                sg.matID = k;
                sg.geometry = geom;
                sg.start = indexData.length * 2;

                sg.count = _data.indices[k].indices.length;

                geom.subGeometrys.push(sg);

                for (var i = 0; i < _data.indices[k].indices.length / 3; i++) {
                    var v0 = _data.indices[k].indices[i * 3 + 0];
                    var v1 = _data.indices[k].indices[i * 3 + 1];
                    var v2 = _data.indices[k].indices[i * 3 + 2];

                    //翻转裁剪信息
                    indexData.push(v0);
                    indexData.push(v2);
                    indexData.push(v1);
                }
            }
            geom.indexCount = indexData.length;
            geom.indexArray = new Uint16Array(indexData);
            //geom.setVertexIndices(0, indexData);
            //geom.indexArray = GameTool.NumberArrayToUint16Array(indexData);

        }
        mapMesh: { [id: string]: { data: egret3d.Geometry, count: number } } = {};
        mapTex: { [id: string]: { data: egret3d.ITexture, count: number } } = {};
        mapAniClip: { [id: string]: { data: FreeNode.AniClipData, count: number } } = {};
        //mapMat: { [id: string]: egret3d.MaterialBase } = {};
        mapMatJson: { [id: string]: { data: any, count: number } } = {};
        mapPrefab: { [id: string]: { data: Entity_Empty | Entity_Mesh, count: number } } = {};
        loadGeom(baseUrl: string, name: string, callback: (geom: egret3d.Geometry, err: Error) => void): void {
            let reskey = name;
            let _si: number = reskey.lastIndexOf("/");
            if (_si >= 0)
                reskey = reskey.substring(_si + 1);

            if (this.mapMesh[reskey] != undefined) {
                this.mapMesh[reskey].count++;
                callback(this.mapMesh[reskey].data, null);
                return;
            }
            loadTool.loadArrayBuffer(baseUrl + name, (a, e) => {
                var _data: FreeNode.MeshData = FreeNode.MeshData.loadMesh(a);
                var geom = new egret3d.Geometry();
                let verticesData = [];
                //geom.verticesData = [];
                geom.vertexAttLength = 0;
                var skin = false;
                if (_data.vec10tpose != null && _data.vec10tpose.length > 0) {
                    skin = true;
                }
                if (skin) {
                    geom.vertexFormat =
                        egret3d.VertexFormat.VF_POSITION | egret3d.VertexFormat.VF_NORMAL | egret3d.VertexFormat.VF_TANGENT | egret3d.VertexFormat.VF_COLOR | egret3d.VertexFormat.VF_UV0 | egret3d.VertexFormat.VF_UV1
                        | egret3d.VertexFormat.VF_SKIN;
                }
                else {
                    geom.vertexFormat =
                        egret3d.VertexFormat.VF_POSITION | egret3d.VertexFormat.VF_NORMAL | egret3d.VertexFormat.VF_TANGENT | egret3d.VertexFormat.VF_COLOR | egret3d.VertexFormat.VF_UV0 | egret3d.VertexFormat.VF_UV1;
                    //     geom.vertexFormat |= egret3d.VertexFormat.VF_SKIN;//全tm是bug,vertexFormat 赋值两次就出错

                }//var skin = true;
                var mbone = this.__FillGeomVertex(verticesData, _data, skin);
                geom.vertexCount = _data.vec3positions.length;
                geom.vertexArray = new Float32Array(verticesData);

                //geom.setVerticesForIndex(0, geom.vertexFormat, verticesData, _data.vec3positions.length);
                //bdata.indices = [];//填充索引数据
                geom["maxbone"] = mbone;
                this.__FillGeomIndex(geom, _data);
                this.mapMesh[reskey] = { data: geom, count: 1 };
                callback(geom, null);
            }
            );
        }
        loadTexture(baseUrl: string, name: string, callback: (img: egret3d.ITexture, err: Error) => void): void {
            let reskey = name;
            let _si: number = reskey.lastIndexOf("/");
            if (_si >= 0)
                reskey = reskey.substring(_si + 1);


            if (this.mapTex[reskey] != undefined) {
                this.mapTex[reskey].count++;
                callback(this.mapTex[reskey].data, null);
                return;
            }
            var img = new Image();
            img.onload = () => {
                this.mapTex[reskey] = { data: new egret3d.ImageTexture(img), count: 1 };
                callback(this.mapTex[reskey].data, null);
            }
            img.onerror = () => {
                //错误资源别放池了
                //this.mapTex[reskey] = { data: egret3d.CheckerboardTexture.texture, count: 1 }

                callback(egret3d.CheckerboardTexture.texture, new Error("img init error"));
            }
            img.src = baseUrl + name;
            //this.mapTex[reskey] = new egret3d.ImageTexture(img);
            //callback(this.mapTex[reskey], null);

            //var loader = new egret3d.URLLoader(baseUrl + name);
            //loader.addEventListener(egret3d.LoaderEvent3D.LOADER_COMPLETE, () =>
            //{
            //    var img = loader.data as egret3d.ImageTexture
            //    this.mapTex[name] = img;
            //    callback(img, null);
            //}, null
            //);
            //loader.addEventListener(egret3d.LoaderEvent3D.LOADER_ERROR, () =>
            //{
            //    this.mapTex[name] = null;
            //    callback(null, new Error("加载贴图失败" + name));
            //}, null
            //);

        }
        loadAniClip(baseUrl: string, name: string, callback: (clip: FreeNode.AniClipData, err: Error) => void): void {
            let reskey = name;
            let _si: number = reskey.lastIndexOf("/");
            if (_si >= 0)
                reskey = reskey.substring(_si + 1);


            if (this.mapAniClip[reskey] != undefined) {
                this.mapAniClip[reskey].count++;
                callback(this.mapAniClip[reskey].data, null);
                return;
            }
            loadTool.loadArrayBuffer(baseUrl + name, (a, e) => {
                var _data: FreeNode.AniClipData = FreeNode.AniClipData.loadClip(a);
                this.mapAniClip[reskey] = { data: _data, count: 1 };
                callback(_data, null);
            }
            );
        }
        private _doLoad(baseUrl: string, count: { json: any[], task: number, finish: number, callback: (groud: FileGroup, err: Error) => void }): void {
            var group = new FileGroup();
            var delayPrefabString: { [id: string]: string } = {};
            var delayParse = () => {
                //当一切完成之后，再处理材质，这个不能现在处理
                //for (var key in delayMatString)
                //{
                //    var json = JSON.parse(delayMatString[key]);
                //    var mat = this.parseMat(json);
                //    this.mapMat[key] = mat;

                //    group.mats[key] = mat;
                //    group.matCount++;
                //}
                //delayMatString = null;
                //和Prefab
                for (var key in delayPrefabString) {
                    if (this.mapPrefab[key] != undefined) {
                        this.mapPrefab[key].count++;
                        group.prefabs[key] = this.mapPrefab[key].data;
                        group.prefabCount++;
                        continue;
                    }
                    else {
                        var json = JSON.parse(delayPrefabString[key]);
                        var prefab = this.parsePrefab(json);
                        this.mapPrefab[key] = { data: prefab, count: 1 };

                        group.prefabs[key] = prefab;
                        group.prefabCount++;
                    }
                }
                delayPrefabString = null;
                count.callback(group, null);
                if (this.delayLoadIndex.length > 0) {
                    var remove = this.delayLoadIndex.splice(0, 1)[0];
                    if (remove.bload) {
                        this.loadIndexFileGroup(remove.indexurl, remove.callback);
                    }
                    else {
                        this.unloadIndexFileGroup(remove.indexurl);
                    }
                }
            }


            count.task++;//防止提前完成，自己也算一个任务
            for (let i = 0; i < count.json.length; i++) {
                let obj = <{}>count.json[i];

                let name = <string>obj["Name"];
                let len = <number>obj["Length"];
                let reskey = name;
                let _si: number = reskey.lastIndexOf("/");
                if (_si >= 0)
                    reskey = reskey.substring(_si + 1);
                //console.log("add name" + i + ":" + name);
                let extname = name.substr(name.indexOf("."));
                if (extname == ".mesh.bin.js") {
                    count.task++;
                    this.loadGeom(baseUrl, name, (geom, _err) => {
                        group.geoms[reskey] = geom;
                        group.geomCount++;

                        count.finish++;
                        if (count.task == count.finish)
                            delayParse();
                    }
                    );
                }
                else if (extname == ".jpg" || extname == ".png") {
                    count.task++;
                    this.loadTexture(baseUrl, name, (tex, _err) => {
                        if (group.texs[reskey] != undefined) {
                            console.log("log 2nd.");
                        }
                        else {
                            group.texs[reskey] = tex;
                            group.texCount++;

                            count.finish++;
                            if (count.task == count.finish)
                                delayParse();
                        }
                    }
                    );
                }
                else if (extname == ".aniclip.bin.js") {
                    count.task++;
                    this.loadAniClip(baseUrl, name, (clip, _err) => {
                        group.anis[reskey] = clip;
                        group.aniCount++;

                        count.finish++;
                        if (count.task == count.finish)
                            delayParse();
                    }
                    );
                }
                else if (extname == ".jsonmat.txt.js") {
                    count.task++;
                    loadTool.loadText(baseUrl + name, (txt, _err) => {
                        group.matrefs.push(reskey);
                        if (this.mapMatJson[reskey] != undefined) {
                            this.mapMatJson[reskey].count++;
                        }
                        else {
                            this.mapMatJson[reskey] = { data: JSON.parse(txt), count: 1 };
                        }
                        count.finish++;
                        if (count.task == count.finish)
                            delayParse();
                    }
                    );
                }
                else if (extname == ".jsontree.txt.js") {
                    count.task++;
                    loadTool.loadText(baseUrl + name, (txt, _err) => {
                        delayPrefabString[reskey] = txt;
                        count.finish++;
                        if (count.task == count.finish)
                            delayParse();
                    }
                    );
                }
            }
            count.finish++;
        }

        private _doUnload(count: { json: any[], task: number, finish: number, callback: (groud: FileGroup, err: Error) => void }) {
            for (let i = 0; i < count.json.length; i++) {
                let obj = <{}>count.json[i];

                let name = <string>obj["Name"];
                let len = <number>obj["Length"];
                let reskey = name;
                let _si: number = reskey.lastIndexOf("/");
                if (_si >= 0)
                    reskey = reskey.substring(_si + 1);
                let extname = name.substr(name.indexOf("."));
                if (extname == ".mesh.bin.js") {
                    var geom = this.mapMesh[reskey];//?how to dispose
                    geom.count--;
                    if (geom.count == 0) {
                        this.mapMesh[reskey] = undefined;
                        egret3d.Context3DProxy.gl.deleteBuffer(geom.data.sharedIndexBuffer);
                        egret3d.Context3DProxy.gl.deleteBuffer(geom.data.sharedVertexBuffer);
                    }

                }
                else if (extname == ".jpg" || extname == ".png") {
                    var tex = this.mapTex[reskey];//?how to dispose
                    if (tex == undefined) {
                        continue;
                    }
                    tex.count--;
                    if (tex.count == 0) {
                        this.mapTex[reskey] = undefined;
                        egret3d.Context3DProxy.gl.deleteBuffer(tex.data.texture2D.textureBuffer);
                    }
                }
                else if (extname == ".aniclip.bin.js") {
                    var ani = this.mapAniClip[reskey];
                    ani.count--;
                    if (ani.count == 0) {
                        this.mapAniClip[reskey] = undefined;
                    }
                }
                else if (extname == ".jsonmat.txt.js") {
                    var mat = this.mapMatJson[reskey];
                    mat.count--;
                    if (mat.count == 0) {
                        this.mapMatJson[reskey] = undefined;
                    }

                }
                else if (extname == ".jsontree.txt.js") {
                    var mesh = this.mapPrefab[reskey];
                    mesh.count--;
                    if (mesh.count == 0) {
                        this.mapPrefab[reskey] = undefined;
                    }
                }
            }

        }
        //加载计数器
        loadCountter: { [id: string]: { json: any[], task: number, finish: number, callback: (groud: FileGroup, err: Error) => void } } = {};


        ///直接加载一组文件
        //从一个.index.txt
        //indexurl index.txt url
        //cacheprefab 是否缓存预设，如果缓存预设，则不要把获取得到的预设直接丢到场景里，而是将它Clone一份使用
        //cacheprefab 如果不缓存预设，则取得的场景图可以直接使用
        //callback 回调
        loadIndexFileGroup(indexurl: string, callback: (group: FileGroup, err: Error) => void) {
            var i = indexurl.lastIndexOf("/");
            var baseurl = indexurl.substring(0, i);

            if (baseurl != "")
                baseurl += "/";

            var countter = this.loadCountter[indexurl];
            if (countter != undefined && (countter.task == 0 || countter.task < countter.finish)) {
                this.delayLoadIndex.push({ bload: true, indexurl: indexurl, callback: callback });
                //countter.callback = callback;
                //countter.task = 0;
                //countter.finish = 0;
                //this._doLoad(baseurl, countter);
                return;
            }
            countter = { json: null, task: 0, finish: 0, callback: callback };
            this.loadCountter[indexurl] = countter;
            loadTool.loadText(indexurl, (_t: string, _e: Error) => {
                countter.json = JSON.parse(_t);
                this._doLoad(baseurl, countter);
            }
            );

        }
        unloadIndexFileGroup(indexurl: string) {
            var countter = this.loadCountter[indexurl];
            if (countter == undefined) {
                return;
            }
            if (countter != undefined && (countter.task == 0 || countter.task < countter.finish)) {//inload
                this.delayLoadIndex.push({ bload: false, indexurl: indexurl, callback: null });
                return;
            }

            this._doUnload(countter);
        }
        delayLoadIndex: { bload: boolean, indexurl: string, callback: (group: FileGroup, err: Error) => void }[] = [];
        parseMat(key: string, mat: egret3d.MaterialBase): void {
            var matjson: any = this.mapMatJson[key].data;
            if (matjson == undefined) return;

            mat.repeat = true;
            mat.getData().repeat = true;
            //if (matjson["repeat"] != undefined) {
            //    let repeat: boolean = matjson["repeat"] as boolean;
            //    mat.repeat = repeat;
            //    mat.getData().repeat = repeat;
            //}

            mat.lightGroup = this.lightgroup;
            //mat.specularColor = 0xffffff;
            //mat.specularLevel = 0.5;
            //mat.ambientColor = 0x111111;
            var name = <string>matjson["shaderName"];
            //if (name == "Egret3D/d/E3D_D_Normal")
            {
                if (matjson["_Color"] != undefined) {
                    var sp = (<string>matjson["_Color"]).split(",");
                    var r = parseInt(sp[0]);// / 255.0;
                    var g = parseInt(sp[1]);// / 255.0;
                    var b = parseInt(sp[2]);// / 255.0;
                    var a = parseInt(sp[3]);// / 255.0;
                    //var c = new egret3d.Color(r, g, b, a);
                    var c = new egret3d.Color(a, r, g, b);

                    mat.diffuseColor = c.getColor();
                    //    mat.diffuseColor = new BABYLON.Color3(r, g, b);
                    //    mat.alpha = a;
                }
                if (matjson["_MainTex"] != undefined) {
                    var tex = matjson["_MainTex"];
                    var texinpool = ResourceMgr.instance().mapTex[tex];
                    if (texinpool == undefined) {
                        mat.diffuseTexture = egret3d.CheckerboardTexture.texture;
                    }
                    else {
                        mat.diffuseTexture = texinpool.data;
                    }
                }

                if (matjson["_DiffuseColor"] != undefined) {
                    var sp = (<string>matjson["_DiffuseColor"]).split(",");
                    var r = parseInt(sp[0]);// / 255.0;
                    var g = parseInt(sp[1]);// / 255.0;
                    var b = parseInt(sp[2]);// / 255.0;
                    var a = parseInt(sp[3]);// / 255.0;
                    //var c = new egret3d.Color(r, g, b, a);
                    //var c = new egret3d.Color(a, r, g, b);
                    var c = new egret3d.Color(180, 180, 180, 180);

                    mat.diffuseColor = c.getColor();
                }

                if (matjson["_AmbientColor"] != undefined) {
                    var sp = (<string>matjson["_AmbientColor"]).split(",");
                    var r = parseInt(sp[0]);// / 255.0;
                    var g = parseInt(sp[1]);// / 255.0;
                    var b = parseInt(sp[2]);// / 255.0;
                    var a = parseInt(sp[3]);// / 255.0;
                    //var c = new egret3d.Color(r, g, b, a);
                    //var c = new egret3d.Color(a, r, g, b);
                    var c = new egret3d.Color(180, 180, 180, 180);
                    mat.ambientColor = c.getColor();
                }

                if (matjson["_SpecularColor"] != undefined) {
                    var sp = (<string>matjson["_SpecularColor"]).split(",");
                    var r = parseInt(sp[0]);// / 255.0;
                    var g = parseInt(sp[1]);// / 255.0;
                    var b = parseInt(sp[2]);// / 255.0;
                    var a = parseInt(sp[3]);// / 255.0;
                    //var c = new egret3d.Color(r, g, b, a);
                    //注意！！！
                    //1、白鹭的api坑爹了，构造函数写的是rgba，实际是argb
                    //2、白鹭跟unity比在颜色方面偏暗，所以要在unity中统一将颜色调亮导出。

                    //var c = new egret3d.Color(a, r, g, b);
                    //为赶版本，暂时在这里将rgba的值都调整为255，回头再让美术单独处理资源再导出
                    var c = new egret3d.Color(180, 180, 180, 180);

                    mat.specularColor = c.getColor();
                }
                if (matjson["_Glossiness"] != undefined) {
                    mat.gloss = <number>matjson["_Glossiness"];
                }
                if (matjson["_specularLevel"] != undefined) {
                    mat.specularLevel = <number>matjson["_specularLevel"];
                }
                if (matjson["_cutAlpha"] != undefined) {
                    mat.cutAlpha = <number>matjson["_cutAlpha"];
                }
                if (matjson["_bothside"] != undefined) {
                    mat.bothside = <boolean>matjson["_bothside"];
                }
            }

            //this.mapMat[key] = mat;
            if (matjson["methods"] != undefined) {
                this.processMethod(mat, matjson["methods"]);
            }
        }

        protected processMethod(mat: egret3d.MaterialBase, methods: any) {
            if (methods["streamerMethod"] != undefined) {
                var streamerData = methods["streamerMethod"];
                var s: egret3d.StreamerMethod = new egret3d.StreamerMethod();
                mat.diffusePass.addMethod(s);

                s.speedU = parseFloat(streamerData["uSpeed"]);
                s.speedV = parseFloat(streamerData["vSpeed"]);
                var textureName: string = streamerData["path"];
                var texinpool = ResourceMgr.instance().mapTex[textureName];
                if (texinpool == undefined) {
                    s.steamerTexture = egret3d.CheckerboardTexture.texture
                }
                else {
                    s.steamerTexture = texinpool.data;
                }
                s.start(true);
            }
        }

        parsePrefab(json: any): Entity_Empty | Entity_Mesh {
            var sceneParser = new SceneParser2(new Parser2());
            var node = <egret3d.Object3D>sceneParser.ParseScene(json);
            return node as Entity_Empty;
        }

    }

    export class Entity_Empty extends egret3d.Entity {
        uuid: number;
        fullname: string;
        //empty 节点 是无法拥有update的
        clone(): Entity_Empty {
            var nnode = new Entity_Empty()
            nnode.uuid = this.uuid;
            nnode.fullname = this.fullname;
            nnode.name = this.name;
            for (var i = 0; i < this.childs.length; i++) {
                if (this.childs[i] instanceof (Entity_Empty) || this.childs[i] instanceof (Entity_Mesh)) {
                    var ss: Entity_Empty = this.childs[i] as Entity_Empty;
                    nnode.addChild(ss.clone());
                }
            }
            return nnode;
        }
        //fix this 02
        findObject3DInChild(name: string, result: egret3d.Object3D[] = null): egret3d.Object3D[] {
            if (result == null)
                result = [];


            if (this.name == name) {
                result.push(this);
            }

            for (var c in this.childs) {
                if (this.childs[c] instanceof (Entity_Empty) || this.childs[c] instanceof (Entity_Mesh)) {
                    (this.childs[c] as Entity_Mesh).findObject3DInChild(name, result);
                }
            }
            return result;

        }
        findObject3DWithSkins(result: Entity_Mesh[] = null): Entity_Mesh[] {
            if (result == null)
                result = [];


            for (var c in this.childs) {
                if (this.childs[c] instanceof (Entity_Empty) || this.childs[c] instanceof (Entity_Mesh)) {
                    (this.childs[c] as Entity_Mesh).findObject3DWithSkins(result);
                }
            }
            return result;
        }
    }
    export class Entity_Mesh extends egret3d.Mesh {

        public roleid: number = -1;
        findObject3DInChild(name: string, result: egret3d.Object3D[] = null): egret3d.Object3D[] {
            if (result == null)
                result = [];

            if (this.name == name) {
                result.push(this);
            }

            for (var c in this.childs) {
                if (this.childs[c] instanceof (Entity_Empty) || this.childs[c] instanceof (Entity_Mesh)) {
                    (this.childs[c] as Entity_Mesh).findObject3DInChild(name, result);
                }
            }
            return result;

        }
        findObject3DWithSkins(result: Entity_Mesh[] = null): Entity_Mesh[] {
            if (result == null)
                result = [];

            if (this.animation instanceof (Skinner)) {
                result.push(this);
            }

            for (var c in this.childs) {
                if (this.childs[c] instanceof (Entity_Empty) || this.childs[c] instanceof (Entity_Mesh)) {
                    (this.childs[c] as Entity_Mesh).findObject3DWithSkins(result);
                }
            }
            return result;
        }
        constructor() {
            super(new egret3d.Geometry(), new egret3d.TextureMaterial());
            this.geometry.vertexArray = new Float32Array(0);
            this.geometry.vertexCount = 0;
            this.geometry.indexArray = new Uint16Array(0);
            this.geometry.indexCount = 0;
        }
        uuid: number;
        fullname: string;

        clone(): Entity_Mesh {
            var nnode = new Entity_Mesh()
            nnode.uuid = this.uuid;
            nnode.fullname = this.fullname;
            nnode.name = this.name;
            nnode.position = this.position.clone();
            nnode.orientation = this.orientation.clone();
            nnode.scale = this.scale.clone();
            //if (nnode.bound instanceof egret3d.BoundBox) {
            //    nnode.bound = new egret3d.BoundBox(nnode, (this.bound as egret3d.BoundBox).min, (this.bound as egret3d.BoundBox).max);
            //} else
            //{
            //此处仍然有白鹭的bug
            //this._bound.owner = nnode;
            nnode.bound = this._bound.clone();
            nnode.bound.owner = nnode;
            //}
            if (this.geometry != null) {
                nnode.geometry = this.geometry;
                nnode.material = this.material;
                for (var i = 0; i < this.materialCount; i++) {
                    nnode.addSubMaterial(i, this.multiMaterial[i]);
                }
            }
            if (this.aniplayer != null) {
                nnode.aniplayer = this.aniplayer.clone(nnode) as AniPlayer;
            }
            if (this.animation != null) {
                nnode.animation = this.animation.clone();
            }
            for (var i = 0; i < this.childs.length; i++) {
                if (this.childs[i] instanceof (Entity_Empty) || this.childs[i] instanceof (Entity_Mesh)) {
                    var ss: Entity_Mesh = (this.childs[i] as Entity_Mesh).clone();
                    nnode.addChild(ss);
                    if (ss.animation instanceof (Skinner)) {
                        var sk = ss.animation as Skinner;
                        sk.fix(ss);
                    }

                }
            }

            if (nnode.aniplayer != null) {
                nnode.aniplayer.fix();
            }
            return nnode;
        }

        //comps: Array<{}> = [];//记录组件信息
        //skiprender: boolean = false;

        update(time: number, delay: number, camera: egret3d.Camera3D): void {
            super.update(time, delay, camera);
            if (this.aniplayer != null) {
                this.aniplayer.update(time, delay);
            }
        }
        rebuildBoundBox() {
            this.buildBoundBox();
        }
        aniplayer: AniPlayer;

    }
}